package com.woniuxy.gobang84.ui;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Optional;
import java.util.function.Predicate;

import com.woniuxy.gobang84.entity.ChessMessage;
import com.woniuxy.gobang84.entity.InviteMessage;
import com.woniuxy.gobang84.entity.Message;
import com.woniuxy.gobang84.entity.Piece;
import com.woniuxy.gobang84.entity.ResultMessage;
import com.woniuxy.gobang84.util.Global;

import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.text.Font;
import javafx.stage.Stage;

/**
 * 对战版棋盘窗口
 *
 * @author 老谭 (<a href="http://www.woniuxy.com">蜗牛学苑</a>)
 *
 */
public class NetGameStage extends Stage {
	private Pane pane = new Pane();
	private boolean canPlay = true;// 决定是否可以落子

	public NetGameStage() {
		// 编写界面代码内容
		// 设置窗体标题
		this.setTitle("蜗牛五子棋");
		// 设计窗体内容
		// 创建布局容器对象(面板)

		// 设置面板颜色
		// pane.setBackground(new Background(new BackgroundFill(new Color(0.5,0.5,0,1),
		// null, null)));
		pane.setBackground(new Background(new BackgroundFill(Color.CHOCOLATE, null, null)));
		// 绘制棋盘
		drawCheckerBoard(pane);

		// 为面板添加鼠标点击事件
		pane.setOnMouseClicked(new EventHandler<MouseEvent>() {
			@Override
			public void handle(MouseEvent event) {
				if (!canPlay) {
//					Alert
					return;
				}
				// 判断游戏是否结束
				if (Global.GAME_OVER) {
					return;
				}
				// System.out.println("鼠标点击"+event.getX()+":"+event.getY());
				// 1、如何使棋子颜色交替出现；√ 2、如何实现只能在棋盘范围内落子; √
				// 判断点击坐标是否在落子范围
				double x = event.getX();
				double y = event.getY();
				if (x < Global.GAME_CHECKERBOARD_MARGIN_SIZE - Global.GAME_CHECKERBOARD_CELL_SIZE / 2
						|| x > Global.GAME_CHECKERBOARD_MARGIN_SIZE + Global.GAME_CHECKERBOARD_LINE_LEN
								+ Global.GAME_CHECKERBOARD_CELL_SIZE / 2
						|| y < Global.GAME_CHECKERBOARD_MARGIN_SIZE - Global.GAME_CHECKERBOARD_CELL_SIZE / 2
						|| y > Global.GAME_CHECKERBOARD_MARGIN_SIZE + Global.GAME_CHECKERBOARD_LINE_LEN
								+ Global.GAME_CHECKERBOARD_CELL_SIZE / 2) {
					return;
				}
				// 3、如何让棋子落在十字中央(棋子矫正位置)√
				// 矫正坐标
				double pieceX = ((int) ((x - Global.GAME_CHECKERBOARD_MARGIN_SIZE
						+ Global.GAME_CHECKERBOARD_CELL_SIZE / 2) / Global.GAME_CHECKERBOARD_CELL_SIZE))
						* Global.GAME_CHECKERBOARD_CELL_SIZE + Global.GAME_CHECKERBOARD_MARGIN_SIZE;
				double pieceY = ((int) ((y - Global.GAME_CHECKERBOARD_MARGIN_SIZE
						+ Global.GAME_CHECKERBOARD_CELL_SIZE / 2) / Global.GAME_CHECKERBOARD_CELL_SIZE))
						* Global.GAME_CHECKERBOARD_CELL_SIZE + Global.GAME_CHECKERBOARD_MARGIN_SIZE;
				// 4、落子防重
				if (containPiece(pieceX, pieceY)) {
					return;
				}
				// 绘制圆形
				Circle circle = new Circle(pieceX, pieceY, Global.GAME_PIECE_RADIUS);
				// 将落子信息定义对象进行存储
				Piece piece;
				if (Global.GAME_PIECE_STATE_FIRST) {
					circle.setFill(Global.GAME_PIECE_FIRST);
					piece = new Piece(pieceX, pieceY, Global.GAME_PIECE_FIRST);
				} else {
					circle.setFill(Global.GAME_PIECE_NEXT);
					piece = new Piece(pieceX, pieceY, Global.GAME_PIECE_NEXT);
				}

				// 棋子状态切换
				Global.GAME_PIECE_STATE_FIRST = !Global.GAME_PIECE_STATE_FIRST;
				pane.getChildren().add(circle);
				// 将落子信息添加到数组
				savePiece(piece);

				// 输赢判断
				isWin(piece);

				// TODO 发送请求到对方
				try {
					Socket socket = new Socket("localhost", Global.oppoPort);
					OutputStream os = socket.getOutputStream();
					ChessMessage chessMessage = new ChessMessage();
					chessMessage.setX(pieceX);
					chessMessage.setY(pieceY);

					ObjectOutputStream oos = new ObjectOutputStream(os);
					oos.writeObject(chessMessage);
					oos.close();

				} catch (IOException e) {
					e.printStackTrace();
				}

				canPlay = false;

			}

		});

		//为关闭窗口注册事件
		setOnCloseRequest(e -> {
			//确认
			//点击确定  System.exit(0);
			//点击取消：e.consumer();
		});

		addNewBtn(pane);
		// 添加悔棋按钮
		addRegretBtn(pane);
		// 保存棋谱按钮
//		addSaveBtn(pane, this);
		// 打谱按钮
//		addReproduceBtn(pane, this);

		// 创建舞台内容容器对象
		Scene scene = new Scene(pane, Global.GAME_WINDOW_WIDTH, Global.GAME_WINDOW_HEIGHT);

		// 将舞台内容容器对象关联到舞台对象中
		setScene(scene);
		// 设置窗体大小不可调整
		setResizable(false);
		// 显示窗体
//		show();

	}

	/**
	 * 增加悔棋按钮
	 * 
	 * @param pane
	 */
	public void addRegretBtn(Pane pane) {
		// 添加悔棋按钮
		Button regretBtn = new Button("悔棋");
		// 设置宽高
		regretBtn.setPrefSize(Global.BTN_WIDTH, Global.BTN_HEIGHT);
		// 设置字体样式和尺寸
		regretBtn.setFont(new Font(Global.BTN_TEXT_TYPE, Global.BTN_TEXT_SIZE));
		// 设置位置
		regretBtn.setLayoutX(Global.REGRET_BTN_X);
		regretBtn.setLayoutY(Global.REGRET_BTN_Y);
		// 添加监听器代码
		regretBtn.setOnMouseClicked(new EventHandler<MouseEvent>() {
			@Override
			public void handle(MouseEvent event) {
				// 悔棋功能
				if (Global.GAME_OVER) {
					return;
				}
				/*
				 * 1、将上一颗棋子从棋盘移除; 2、将上一颗棋子对象从PIECES中移除; 3、对棋子状态进行取反;
				 * 
				 */
				// 获取存储面板元素的集合对象
				ObservableList<Node> list = pane.getChildren();
				// 如何防止移除除棋子以外的对象？
				if (Global.PIECES.size() > 0) {
					list.remove(list.size() - 1);
//					2、将上一颗棋子对象从PIECES中移除;
					Global.PIECES.remove(Global.PIECES.size() - 1);
//					3、对棋子状态进行取反;
					Global.GAME_PIECE_STATE_FIRST = !Global.GAME_PIECE_STATE_FIRST;
				}

			}
		});
		// 将按钮添加到面板
		pane.getChildren().add(regretBtn);
	}

	public void addNewBtn(Pane pane) {
		// 添加新局按钮
		Button newBtn = new Button("新局");
		// 设置宽高
		newBtn.setPrefSize(Global.BTN_WIDTH, Global.BTN_HEIGHT);
		// 设置字体样式和尺寸
		newBtn.setFont(new Font(Global.BTN_TEXT_TYPE, Global.BTN_TEXT_SIZE));
		// 设置位置
		newBtn.setLayoutX(Global.NEW_BTN_X);
		newBtn.setLayoutY(Global.NEW_BTN_Y);
		// 添加监听器代码
		newBtn.setOnMouseClicked(new EventHandler<MouseEvent>() {

			@Override
			public void handle(MouseEvent event) {
				// 发送对战邀请消息
				Message iniviteMessage = InviteMessage.INVITE;
				try {
					Socket socket = new Socket(Global.oppoIp, Global.oppoPort);
					OutputStream os = socket.getOutputStream();
					ObjectOutputStream oos = new ObjectOutputStream(os);
					oos.writeObject(iniviteMessage);
					oos.close();
				} catch (UnknownHostException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		});
		// 将按钮添加到面板
		pane.getChildren().add(newBtn);
	}

	public void clearPiece(Pane pane) {
		// 1、清除棋盘上的棋子数据;
		// 获取存储面板元素的集合对象
		ObservableList<Node> list = pane.getChildren();
		// removeIf():遍历当前集合所有元素，分别调用test方法，根据test方法返回结果决定是否移除当前元素
		list.removeIf(new Predicate<Node>() {
			@Override
			public boolean test(Node t) {
				return t instanceof Circle;
			}
		});
		// 2、清空PIECES中所有棋子信息;
		Global.PIECES.clear();
		// 3、棋子颜色进行初始化;
		Global.GAME_PIECE_STATE_FIRST = true;
		// 4、重置gameOver;
		Global.GAME_OVER = false;
	}

	// 判断指定坐标是否存在棋子
	private boolean containPiece(double pieceX, double pieceY) {
		for (int index = 0; index < Global.PIECES.size(); index++) {
			Piece oldPiece = Global.PIECES.get(index);
			if (oldPiece != null && oldPiece.getX() == pieceX && oldPiece.getY() == pieceY) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 将指定棋子对象存储到数组中 将指定棋子对象存储到数组中
	 * 
	 * @param piece
	 */
	private void savePiece(Piece piece) {
		Global.PIECES.add(piece);
		// for(int index=0;index<Global.PIECES.size();index++){
		// if(Global.PIECES.get(index)==null){
		// Global.PIECES.add(piece);
		// break;
		// }
		// }
	}

	public void isWin(Piece piece) {
		// 水平方法
		// 存储同色连棋数量
		int count = 1;
		// 向左<-
		for (int j = 1; j < 5; j++) {
			boolean state = false;
			for (int index = 0; index < Global.PIECES.size(); index++) {
				// 旧棋子
				Piece oldPiece = Global.PIECES.get(index);
				// 目标坐标
				double aimX = piece.getX() - Global.GAME_CHECKERBOARD_CELL_SIZE * j;
				double aimY = piece.getY();
				/*
				 * if(oldPiece!=null && oldPiece.getX()==aimX && oldPiece.getY()==aimY &&
				 * oldPiece.getColor().equals(piece.getColor())){
				 */
				// 将目标棋子信息存储到对象
				Piece aimPiece = new Piece(aimX, aimY, piece.getColor());
				// 比较目标棋子与数组中棋子对象进行比较(坐标和颜色是否相同)
				if (aimPiece.equals(oldPiece)) {
					// 计数加一
					count++;
					// 将棋子状态设置为找到
					state = true;
					break;
				}
			}
			// 如果目标棋子未找到(说明不是连子)，结束此方向查找
			if (!state) {
				break;
			}
		}
		// 向右 ->
		for (int j = 1; j < 5; j++) {
			boolean state = false;
			for (int index = 0; index < Global.PIECES.size(); index++) {
				// 旧棋子
				Piece oldPiece = Global.PIECES.get(index);
				// 目标坐标
				double aimX = piece.getX() + Global.GAME_CHECKERBOARD_CELL_SIZE * j;
				double aimY = piece.getY();
				/*
				 * if(oldPiece!=null && oldPiece.getX()==aimX && oldPiece.getY()==aimY &&
				 * oldPiece.getColor().equals(piece.getColor())){
				 */
				Piece aimPiece = new Piece(aimX, aimY, piece.getColor());
				if (aimPiece.equals(oldPiece)) {
					count++;
					state = true;
					break;
				}
			}
			if (!state) {
				break;
			}
		}
		if (count > 4) {
			// 消息框
			// Alert alert=new Alert()
			showWinInfor();
			Global.GAME_OVER = true;
			return;
		}
		// 重置count
		count = 1;
		// 垂直方向判断
		// 向上
		for (int j = 1; j < 5; j++) {
			boolean state = false;
			for (int index = 0; index < Global.PIECES.size(); index++) {
				// 旧棋子
				Piece oldPiece = Global.PIECES.get(index);
				// 目标坐标
				double aimX = piece.getX();
				double aimY = piece.getY() - Global.GAME_CHECKERBOARD_CELL_SIZE * j;
				/*
				 * if(oldPiece!=null && oldPiece.getX()==aimX && oldPiece.getY()==aimY &&
				 * oldPiece.getColor().equals(piece.getColor())){
				 */
				Piece aimPiece = new Piece(aimX, aimY, piece.getColor());
				if (aimPiece.equals(oldPiece)) {
					count++;
					state = true;
					break;
				}
			}
			if (!state) {
				break;
			}
		}
		// 向下
		for (int j = 1; j < 5; j++) {
			boolean state = false;
			for (int index = 0; index < Global.PIECES.size(); index++) {
				// 旧棋子
				Piece oldPiece = Global.PIECES.get(index);
				// 目标坐标
				double aimX = piece.getX();
				double aimY = piece.getY() + Global.GAME_CHECKERBOARD_CELL_SIZE * j;
				/*
				 * if(oldPiece!=null && oldPiece.getX()==aimX && oldPiece.getY()==aimY &&
				 * oldPiece.getColor().equals(piece.getColor())){
				 */
				Piece aimPiece = new Piece(aimX, aimY, piece.getColor());
				if (aimPiece.equals(oldPiece)) {
					count++;
					state = true;
					break;
				}
			}
			if (!state) {
				break;
			}
		}
		if (count > 4) {
			showWinInfor();
			Global.GAME_OVER = true;
			return;
		}
		// 重置count
		count = 1;
		// 从左上到右下斜向判断\
		// 左上角
		for (int j = 1; j < 5; j++) {
			boolean state = false;
			for (int index = 0; index < Global.PIECES.size(); index++) {
				// 旧棋子
				Piece oldPiece = Global.PIECES.get(index);
				// 目标坐标
				double aimX = piece.getX() - Global.GAME_CHECKERBOARD_CELL_SIZE * j;
				double aimY = piece.getY() - Global.GAME_CHECKERBOARD_CELL_SIZE * j;
				/*
				 * if(oldPiece!=null && oldPiece.getX()==aimX && oldPiece.getY()==aimY &&
				 * oldPiece.getColor().equals(piece.getColor())){
				 */
				Piece aimPiece = new Piece(aimX, aimY, piece.getColor());
				if (aimPiece.equals(oldPiece)) {
					count++;
					state = true;
					break;
				}
			}
			if (!state) {
				break;
			}
		}
		// 右下角判断
		for (int j = 1; j < 5; j++) {
			boolean state = false;
			for (int index = 0; index < Global.PIECES.size(); index++) {
				// 旧棋子
				Piece oldPiece = Global.PIECES.get(index);
				// 目标坐标
				double aimX = piece.getX() + Global.GAME_CHECKERBOARD_CELL_SIZE * j;
				double aimY = piece.getY() + Global.GAME_CHECKERBOARD_CELL_SIZE * j;
				/*
				 * if(oldPiece!=null && oldPiece.getX()==aimX && oldPiece.getY()==aimY &&
				 * oldPiece.getColor().equals(piece.getColor())){
				 */
				Piece aimPiece = new Piece(aimX, aimY, piece.getColor());
				if (aimPiece.equals(oldPiece)) {
					count++;
					state = true;
					break;
				}
			}
			if (!state) {
				break;
			}
		}
		if (count > 4) {
			showWinInfor();
			Global.GAME_OVER = true;
			return;
		}
		// 重置count
		count = 1;
		// 从左下到右上斜向判断/
		// 左下角
		for (int j = 1; j < 5; j++) {
			boolean state = false;
			for (int index = 0; index < Global.PIECES.size(); index++) {
				// 旧棋子
				Piece oldPiece = Global.PIECES.get(index);
				// 目标坐标
				double aimX = piece.getX() - Global.GAME_CHECKERBOARD_CELL_SIZE * j;
				double aimY = piece.getY() + Global.GAME_CHECKERBOARD_CELL_SIZE * j;
				/*
				 * if(oldPiece!=null && oldPiece.getX()==aimX && oldPiece.getY()==aimY &&
				 * oldPiece.getColor().equals(piece.getColor())){
				 */
				Piece aimPiece = new Piece(aimX, aimY, piece.getColor());
				if (aimPiece.equals(oldPiece)) {
					count++;
					state = true;
					break;
				}
			}
			if (!state) {
				break;
			}
		}
		// 右上角判断
		for (int j = 1; j < 5; j++) {
			boolean state = false;
			for (int index = 0; index < Global.PIECES.size(); index++) {
				// 旧棋子
				Piece oldPiece = Global.PIECES.get(index);
				// 目标坐标
				double aimX = piece.getX() + Global.GAME_CHECKERBOARD_CELL_SIZE * j;
				double aimY = piece.getY() - Global.GAME_CHECKERBOARD_CELL_SIZE * j;
				/*
				 * if(oldPiece!=null && oldPiece.getX()==aimX && oldPiece.getY()==aimY &&
				 * oldPiece.getColor().equals(piece.getColor())){
				 */
				Piece aimPiece = new Piece(aimX, aimY, piece.getColor());
				if (aimPiece.equals(oldPiece)) {
					count++;
					state = true;
					break;
				}
			}
			if (!state) {
				break;
			}
		}
		if (count > 4) {
			showWinInfor();
			Global.GAME_OVER = true;
			return;
		}
		//判断胜负，一定胜，发送自己账号，对战结果 封装到ResultMessage发送给对方
	}

	public void showWinInfor() {
		String mes;
		if (Global.GAME_PIECE_STATE_FIRST) {
			mes = "后手";
		} else {
			mes = "先手";
		}
		Alert alert = new Alert(AlertType.INFORMATION);
		// 设置消息内容
		alert.setContentText("恭喜" + mes + "赢得了比赛!");
		// 设置标题
		alert.setTitle("对战结果: ");
		// 展示弹窗
		alert.show();
	}

	private void drawCheckerBoard(Pane pane) {
		// 水平线条绘制
		for (int row = 0; row <= Global.GAME_CHECKERBOARD_CELL_NUM; row++) {
			// 绘制棋盘
			Line line = new Line(Global.GAME_CHECKERBOARD_MARGIN_SIZE,
					Global.GAME_CHECKERBOARD_MARGIN_SIZE + Global.GAME_CHECKERBOARD_CELL_SIZE * row,
					Global.GAME_CHECKERBOARD_MARGIN_SIZE + Global.GAME_CHECKERBOARD_LINE_LEN,
					Global.GAME_CHECKERBOARD_MARGIN_SIZE + Global.GAME_CHECKERBOARD_CELL_SIZE * row);

			// 将组件添加到面板容器
			pane.getChildren().add(line);
		}
		// 垂直线条绘制
		for (int col = 0; col <= Global.GAME_CHECKERBOARD_CELL_NUM; col++) {
			// 绘制棋盘
			Line line = new Line(Global.GAME_CHECKERBOARD_MARGIN_SIZE + Global.GAME_CHECKERBOARD_CELL_SIZE * col,
					Global.GAME_CHECKERBOARD_MARGIN_SIZE,
					Global.GAME_CHECKERBOARD_MARGIN_SIZE + Global.GAME_CHECKERBOARD_CELL_SIZE * col,
					Global.GAME_CHECKERBOARD_MARGIN_SIZE + Global.GAME_CHECKERBOARD_LINE_LEN);

			// 将组件添加到面板容器
			pane.getChildren().add(line);
		}
	}

	/**
	 * 用于处理客户端消息是，更新主棋盘界面
	 * 
	 * @param chessMessage
	 */
	public void updateUI(Message message) {
		// 判断具体是哪种消息
		if (message instanceof ChessMessage) {
			ChessMessage chessMessage = (ChessMessage) message;
			Circle circle = new Circle(chessMessage.getX(), chessMessage.getY(), Global.GAME_PIECE_RADIUS);
			// 将落子信息定义对象进行存储
			Piece piece;
			if (Global.GAME_PIECE_STATE_FIRST) {
				circle.setFill(Global.GAME_PIECE_FIRST);
				piece = new Piece(chessMessage.getX(), chessMessage.getY(), Global.GAME_PIECE_FIRST);
			} else {
				circle.setFill(Global.GAME_PIECE_NEXT);
				piece = new Piece(chessMessage.getX(), chessMessage.getY(), Global.GAME_PIECE_NEXT);
			}

			// 棋子状态切换
			Global.GAME_PIECE_STATE_FIRST = !Global.GAME_PIECE_STATE_FIRST;
			pane.getChildren().add(circle);
			// 将落子信息添加到数组
			savePiece(piece);

			// 输赢判断
//			isWin(piece);

			canPlay = true;
		} else if (message instanceof InviteMessage) { // 对战邀请的消息
			InviteMessage inviteMessage = (InviteMessage) message;

			if (inviteMessage.getFlag() == 1) { // 对方发出邀请
				Alert alert = new Alert(AlertType.CONFIRMATION, "对方邀请您对战一局，敢否迎战?", ButtonType.OK, ButtonType.CANCEL); // 确认按钮
				alert.setTitle("对战邀请");
				Optional<ButtonType> buttonType = alert.showAndWait();
				if (buttonType.get() == ButtonType.OK) {
					// 发送消息到对方
					Message msg = inviteMessage.AGREE;
				} else {
					// 发送消息到对方
					Message msg = inviteMessage.REFUSE;
				}

			} else if (inviteMessage.getFlag() == 2) { // 自己发的对战邀请，对方同意对战

			} else if (inviteMessage.getFlag() == 3) { // 自己发的对战邀请，对方拒绝对战

			}
		}else if (message instanceof ResultMessage) {
			//从消息中获取对方的账号及对战结果，加上自己的账号，调用ResordService的add方法
		}

	}
}
